// cf-300d
// 题意：
// 给定一个n(<=10^9)行，n列的方块，初始方块边界外都被黑色边界包围，
// 现在你可以涂这个方块k次，每次涂都必须满足下面要求：
// 1. 你必须选择一个方块，并且方块边界都是被黑色包围，内部没有一块黑色；
// 2. 你可以选择一行一列然后把他们染成黑色，使得新画完的格子和原来的
//    黑色边界组成组成非空的正方形区域。
//
// 问最终有多少中不同的染色方案。不同的染色方案只要最后结果不一样就算不同。
//
// 题解：
// 因为每一步都要求是方块，而且又是四分，所以对于某个正方形来说，k不会很大。
//
// 然后我们可以从小往大推导，假如说已经算出来 f[n][k]，那么推导到 f[2*n][k]
// 的时候，我们只需要将 f[n] 看成一个多项式，即 g(x)=sigma(f[n][k]*x^k)，
// 那么 g(x)^4 就是我们要求的2*n的答案，而且我们只需要保留题目所需要的k
// 项就行。
//
// 这个题目也可以看成一个树形dp，因为染色的过程生成的都是树，而且最终态
// 就是某个结点以及它到根的路径上都被染成黑色。可以dp之。
//
// run: $exec < input
#include <iostream>
#include <vector>

int const mo = 7340033;
int const maxk = 1007;
int rev_mo[mo];

using ll = long long;

// TODO calc Modular multiplicative inverse
void calc_rev_mo()
{
	rev_mo[1] = 1;
	for (int i = 2; i < mo; i++)
		rev_mo[i] = (mo - (mo / i) * rev_mo[mo % i] % mo) % mo;
}

std::vector<std::vector<ll>> dp(32, std::vector<ll>(maxk, 0));
std::vector<ll> res;

namespace ntt
{
	int rev[4 * maxk];
	int const mo = 7340033;
	ll const root = 5;
	ll const rroot = 4404020;
	ll const root_pw = 1 << 20;

	ll mod(ll x) { return ((x % mo) + mo) % mo; }

	void ntt(std::vector<ll> & a, bool invert)
	{
		int n = a.size();
		for (int i = 0; i < n; i++)
			if (i < rev[i]) std::swap(a[i], a[rev[i]]);

		for (int len = 2; len <= n; len *= 2) {
			int len2 = len / 2;
			ll wlen = invert ? rroot : root;
			for (int i = len; i < root_pw; i *= 2)
				wlen = (wlen * wlen) % mo;
			for (int i = 0; i < n; i += len) {
				ll w = 1;
				for (int j = 0; j < len2; j++) {
					ll u = a[i + j], v = (a[i + j + len2] * w) % mo;
					a[i + j] = mod(u + v);
					a[i + j + len2] = mod(u - v);
					w = (w * wlen) % mo;
				}
			}
		}

		if (!invert) return;
		ll nrev = rev_mo[n];
		for (int i = 0; i < n; i++)
			a[i] = (a[i] * nrev) % mo;
	}

	int calc_last = -1;

	void calc_rev(int n)
	{
		if (n == calc_last) return;
		calc_last = n;
		int logn = 0;
		while ((1 << logn) < n) logn++;
		for (int i = 0; i < n; i++) {
			rev[i] = 0;
			for (int j = 0; j < logn; j++)
				if (i & (1 << j))
					rev[i] |= 1 << (logn - j - 1);
		}
	}

	void multiply(std::vector<ll> const& a, std::vector<ll> const& b, std::vector<ll> & res)
	{
		std::vector<ll> fa(a.begin(), a.end());
		std::vector<ll> fb(b.begin(), b.end());
		size_t n = 1;
		while (n < std::max(a.size(), b.size())) n *= 2;
		n *= 2;
		fa.resize(n); fb.resize(n);

		calc_rev(n);
		ntt(fa, false); ntt(fb, false);
		for (size_t i = 0; i < n; i++) fa[i] *= fb[i];
		ntt(fa, true);
		res.resize(n);
		for (size_t i = 0; i < n; i++) res[i] = fa[i] % mo;
	}
}

void init_dp()
{
	for (int i = 0; i < 30; i++) {
		dp[i][0] = 1;
		ntt::multiply(dp[i], dp[i], res);
		res.resize(maxk);
		ntt::multiply(res, res, dp[i + 1]);
		dp[i + 1].insert(dp[i + 1].begin(), 0);
		dp[i + 1].resize(maxk);
	}
}

void init()
{
	calc_rev_mo();
	init_dp();
}

int main()
{
	std::ios_base::sync_with_stdio(false);
	init();
	int q; std::cin >> q;
	while (q--) {
		ll n, k; std::cin >> n >> k;
		int iter = 0;
		for (; n > 1 && (n & 1); iter++) n /= 2;
		std::cout << dp[iter][k] << "\n";
	}
}

